/*******************************************
 *  
 *   All global variables are defined here.
 *
 *****************************************************/

#ifndef GLOBAL_H
#define GLOBAL_H

#include "crossbit/common.h"
#include "crossbit/Exit.h"
#include "stdlib.h"
#include "stack"
#include "map"
#include "vector"
#include "stdio.h"
#include <signal.h>

#define EXIT_BLOCKS (1000)
#define HASH_TABLE_SIZE ( 1 << 15 )

namespace crossbit{

    class TBlock;
    class VBlock;
    struct Exit;

    class GLOBAL{
        public:
            // the index of the last <code>Exit</code> when control transfer comes back to Crossbit
            static XTUint32 last_exit;
            // the <code>SPC</code> of the next block 
            static XTUint32 next_address;
            // when Crossbit executes the translated code, it first saves the esp register to <code>saved_esp</code>, 
            // when control transfer comes back to Crossbit, it assigns the esp register with the value in <code>saved_esp</code> 
            static XTUint32 saved_esp;
            static XTUint32 return_count;
            // the total size of an executable memory space, where stores corresponding instructions to evry <code>Exit</code>  
            static const XTUint32 EXIT_STUB_SIZE = ( 1 << 23 );
            // the start address of the current <code>Exit</code>
            static XTMemAddr exit_stub_base;
            // the end address of the Exits 
            static XTMemAddr exit_stub_end;
            
            static const XTUint32 SUPER_STUB_SIZE = ( 1 << 23 );
            /* the start address of the super stub , a super stub contains two instructions : 
                    1) mov a Tblock pointer to GLOBAL::BUILD_SUPER_BLOCK 
                    1) jump to GLOBAL::swith_addr
            */
            static XTMemAddr super_stub_base;
            // the end address of the super_stub 
            static XTMemAddr super_stub_end;

            // if the translated code want to jump back to Crossbit,
            // it first jump to the address, whose value is saved in switch_addr
            static XTMemAddr switch_addr;
            // the address in executable memory space, where contains several simple hash dispath instructions to 
            // handle the indirect branch
            static XTMemAddr hashtable_dispatch;	
            // used to calculate the the hash value of a spc : key = TABLE_MASK & spc
            const static XTUint32 TABLE_MASK = ( HASH_TABLE_SIZE << 1 ) - 1;

            // indirect hashtable , contains <spc,tpc> pairs
            static XTMemAddr indirect_hashtable[HASH_TABLE_SIZE];
            // assume the the call recursion is no more than 1000 times
            // static XTMemAddr return_addr_stack[1000]; //FIXME: obsolete ?
            volatile static XTUint32 return_address;
            // return_stack : < mem_addr , spc > 
            static std::stack<std::pair<XTMemAddr, XTMemAddr> > return_stack; 
            // return_map : 1) return_map.frist : the spc . 
            //              2) return_map.second : a vector of translated memaddress , where the corresponding
            //                 tpc of spc should be put 
            static std::map<XTMemAddr , std::vector<XTMemAddr> * > return_map;

            // for trace linking
            static TBlock* tblock_stub;
            static VBlock* vblock_stub;

            // the top address of the simulated stack
            static const XTMemAddr STACK_BASE = 0x40000000;

            // The max number of block number in a super block chain
            static const XTUint32 MAX_BLOCK_CHAIN_NUM = 31;
            // The threshold of a basic block , if it runs more than this value , it is
            // considered to be a head of a super block
            static const XTUint32 THRESHOLD = 3000;
            // a flag to determine if it should build a super block
            static XTUint32 BUILD_SUPER_BLOCK;
            // the max virtual registers could be used
            static const XTUint32 MAX_VREG = 100;
            // the number of <code>Exit</code> could be used, 
            static XTUint32 total_exit;
            // the value in <code>exit_stub</code> is a pointer to an array of 1000 <code>Exit</code> 
            static XTMemAddr exit_stub[1000];
            // reqeust an <code>Exit</code>
            static Exit* requestExit() ;
            // get the <code>Exit</code>'s pointer by the index of the <code>Exit</code>
            static Exit* getExit( XTUint32 exit_number ) ;
            // check if a <code>VBlock</code> a call , only used in mips front-end
            static bool  checkCall( VBlock * vblock );

			// contants, for signal context switch only
            static XTMemAddr sig_ret_addr;
            static XTUint32 SIG_RET;
			static sigset_t SIG_FULL_SET;
			static sigset_t SIG_ON_SET;
			static sigset_t SIG_ON_OLDSET;
			static XTInt32 SIG_HOW;

    }; // GLOBAL

} // crossbit

#endif
